<?php

/**
 * This file is part of the Pagizer package.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright   Copyright (c) 2010 Advisa (http://www.advisa.fr)
 * @author      Pagizer Core Team <team@pagizer.org>
 * @package     pagizer
 * @subpackage  website
 */

class m_website_services_PageService extends f_core_Service
{
	/**
	 * @var m_website_services_PageService
	 */
	private static $instance;
	
	/**
	 * Constructor
	 */
	private function __construct()
	{
		// Code if needed...
	}
	
	/**
	 * @return m_website_services_PageService
	 */
	public static function getInstance()
	{
		if (self::$instance === null)
		{
			self::$instance = new self();
		}
		return self::$instance;
	}
	
	/**
	 * Get all drag & drop blocks from all modules
	 *
	 * @return array
	 */
	public function getBlocksXmlParameters($lang = null)
	{
		$fileResolver = f_file_Resolver::getInstance();
		
		if(is_null($lang)) $lang = $this->getContextLang();
		
		$files = $fileResolver->fromDirectory(MODULES_DIR)->setMask('config/blocks.xml')->setRecursive(true)->find();
		
		if(count($files) > 0)
		{
			$result = array();
			
			foreach($files as $file)
			{
				$xmlFile = f_xml_Xpath::getInstance($fileResolver->getOverload($file));
				
				$modulePath = explode(DIRECTORY_SEPARATOR, $file);
				$module = $modulePath[count($modulePath)-3];
				
				$xmlBlocks = $xmlFile->fromXpath('block')->getElements();

                $moduleKey = $xmlFile->getElementValueFromXpath('category/key');
                $label = $xmlFile->getElementValueFromXpath('category/label');
                $priority = $xmlFile->getElementValueFromXpath('category/priority');

                if(is_null($moduleKey))
                {
                    $moduleKey = $module;
                    $label = $module;
                    $priority = 0;
                }
                
				$result[$moduleKey]['label'] = $label;
				$result[$moduleKey]['priority'] = intval($priority);

				$block = array();				
				
				/* @var $element f_Xml_XmlElement */
				foreach($xmlBlocks as $element)
				{
					$rawValues = '';
					$block = $element->getAttributes();
										
					$block['module'] = $module;
					
					$defaultParams = $element->getSubElements('defaultParam');

					if(is_array($defaultParams) && count($defaultParams) > 0)
					{
						foreach ($defaultParams as $defaultParam)
						{
							$param = $defaultParam->getAttributes();
							$block[$param['name']] = $param['value'];
						}
					}
					
					$neededFields = array('action', 'blockLabel', 'blockIcon', 'module');

                    if(count(array_diff($neededFields, array_keys($block))) > 0)
                    {
                       throw new Exception('Needed field is not set in block declaration file');
                    }

                    if(!isset($block['editAction']))
                    {
                        $block['isEditable'] = 'false';
                    }
					
					$block['blockLang'] = $lang;
					
					foreach($block as $key => $arrayBlock)
					{									
						if($key != 'editAction')
						{
							$rawValues .= $key.'="'.$arrayBlock.'" ';
						}

					}
					
                    $block['rawValues'] = $rawValues;
                    
                    $cat = $element->getSubElements('category');

                    if(!is_null($cat))
                    {
                        $module = $cat[0]->getContent();
                        if(!isset($result[$module]['priority']))
                        {
                            $result[$module]['priority'] = 0;
                        }
                        $result[$module]['blocks'][] = $block;

                    }
                    else
                    {
                        $result[$moduleKey]['blocks'][] = $block;
                    }
					
				}
			}
		}

        foreach($result as $key => $val)
        {
            if(!isset($val['label']))
            {
                $result[$key]['label'] = $key;
            }

            if(count($result[$key]['blocks']) == 0)
            {
                unset($result[$key]);
            }
            else
            {
                $p[$key] = $result[$key]['priority'];
                $l[$key] = $result[$key]['label'];
            }
        }
        
        array_multisort($p, SORT_DESC, $l, SORT_ASC, $result);

		return $result;
	}
	
	/**
	 * Get edition smarty block tag for drag & drop block edition
	 *
	 * @param string $blockParams
	 * @param integer $pageId
	 * @return string
	 */
	public function getBlockEditBlock($blockParams, $pageId, $pageLang)
	{	
		$xmlFile = MODULES_DIR.DIRECTORY_SEPARATOR.$blockParams['module'].DIRECTORY_SEPARATOR."config".DIRECTORY_SEPARATOR."blocks.xml";

        $xmlFile = f_file_Resolver::getInstance()->getOverload($xmlFile);

		$result = '';

        $xmlBlockParams = f_xml_Xpath::getInstance($xmlFile)->getElementFromXpath("block[@action='".$blockParams['action']."']");

        /* @var $xmlBlockParams f_xml_XmlElement */
        if(!is_null($xmlBlockParams))
        {
            $result = '{block module="'.$blockParams['module'].'" action="'.$xmlBlockParams->getAttributeValue('editAction').'" pageId="'.$pageId.'" pageLang="'.$pageLang.'" ';

            unset($blockParams['module'], $blockParams['action'], $blockParams['rawValues']);

            foreach($blockParams as $paramName => $blockParam)
            {
                $result .= $paramName.'="'.$blockParam.'" ';
            }

            $result .= "}";
        }


        return $result;
	}

    /**
     *
     * @param array $blockParams
     * @return f_xml_XmlElement
     */
    public function getXmlBlockParams($blockParams)
    {
        $xmlFile = MODULES_DIR.DIRECTORY_SEPARATOR.$blockParams['module'].DIRECTORY_SEPARATOR."config".DIRECTORY_SEPARATOR."blocks.xml";
        $xmlFile = f_file_Resolver::getInstance()->getOverload($xmlFile);
        
		if(is_file($xmlFile))
		{
            $block = f_xml_Xpath::getInstance($xmlFile)->getElementsFromXpath('block[@action="'.$blockParams['action'].'"]');

            if(isset($block[0]))
            {
                $blockParam = $block[0];
            }
            else
            {
                $blockParam = null;
            }

            return $blockParam;
        }
        return null;
    }

    public function isBlockEditable($blockParams)
	{
        $blockParam = $this->getXmlBlockParams($blockParams);

        /* @var $blockParam f_xml_XmlElement */
        return !is_null($blockParam->getAttributeValue('editAction'));
	}
	
	/**
	 * Get website's available layouts templates name and label
	 * Will retrieve from modules/website/config/templates
	 * 
	 * @return array
	 */
	public function getTemplates($themeName = null, $website = null)
	{
        if(is_null($themeName)) $themeName = FRONT_THEME;
		$files = f_file_Resolver::getInstance()->fromDirectory(HTTP_DIR.DS.'themes'.DS.$themeName.DS.'frontend'.DS.'layouts')->setMask("*.xml")->find();
		$result = array();
		$check = array();

		if(is_array($files) && isset($files[0]))
		{
			foreach ($files as $file)
			{
				$res = array();
				$fileName = str_replace(".xml", "", f_file_File::getInstance($file)->getBaseName());
				$check[] = $fileName;
				$res["fileName"] = $fileName;
				$res["label"] = f_xml_Xpath::getInstance($file)->getAttributeValue("label");
				$result[] = $res;
			}			
		}

        if(!is_null($website))
        {
            $docProvider = f_document_Provider::getInstance();
            $recordedLayouts = $docProvider ->loadDocuments('modules_website/layout')
                                            ->whereIsEqual('websiteId', $website->getUniqueId())
                                            ->retrieveDocuments($website->getLang());

            if(count($recordedLayouts) > 0)
            {
                foreach($recordedLayouts as $layout)
                {
                    $res["fileName"] = $layout->getUniqueId();
                    $res["label"] = $layout->getLabel();
                    $result[] = $res;
                }
            }
        }

		return $result;
	}

    /**
     * Get the dynamic URL for a document, for the front.
     * @param <object> $doc
     * @param <object> $page
     * @param <array> $paramaters
     * @return <string>
     */
	public function getDynamicUrl($doc, $page = null, $parameters = array())
	{
		if(is_null($page))
		{
			$page = f_core_Context::getInstance()->getContext("currentPage");
		}

        if(isset($parameters['url']) && !empty($parameters['url']))
        {
            $urlDoc = f_core_Routing::formatStringForUrl($parameters['url'], true);
            unset($parameters['url']);
        }
        else
        {
            $urlDoc = method_exists($doc, "getUrl") ? $doc->getUrl() : f_core_Routing::formatStringForUrl($doc->getLabel(), true);
        }

        if(!empty($urlDoc))
        {
            $pageId = $page->getUniqueId();
            $url = $page->getCompleteUrl();

            $url = preg_replace('/\/<(.*)>/', '', $url);

            $params = "";

            if(!empty($parameters))
            {
                $nb = count($parameters);
                for($i = 0; $i < $nb; $i++)
                {
                    $parameters[$i] = f_core_Routing::formatStringForUrl($parameters[$i], true);
                }
                $params = "/".implode('/',$parameters);
            }

            $url = $url."/".$urlDoc.$params;

            return $url;
        }
		
		return null;
	}

	/**
	 * Redirect to a targeted page
	 * @param string $targetName
	 * @param string $lang
	 */
	public function redirectToTargetedPage($targetName, $websiteId, $lang)
	{
	    $page = f_target_Manager::getDocumentByUniqueTarget($targetName, $websiteId, $lang);

	    if(is_object($page) && $page instanceof m_website_documents_Page)
	    {
            $url = $page->getCompleteUrl();
            header("Location: $url");
	    }
	    else
	    {
            if($targetName == "404")
            {
                header("HTTP/1.0 404 Not Found");
                header("Status: 404 Not Found");
                ob_end_clean();
                $tplEngine = f_template_Template::getInstance();
                $tplEngine->setModuleTemplate("website", "front/layout/404.html");
                $tplEngine->renderDisplay();
                die();
            }
            else
            {
                $this->redirectToTargetedPage("404", $websiteId, $lang);
            }
	    }
	}

	/**
	 * Extract blocks parameters in array from a given text content
	 *
	 * @var string $content
	 * @return array
	 */
	public function rawParamsToArray($content)
	{
        preg_match_all('`(.*?)="(.*?)"`', stripslashes($content), $params);

        foreach ($params[1] as $k => $param)
        {
            $result[trim($param)] = $params[2][$k];
        }

		return $result;
	}

    public function getBlockButtons($blockParams, $page, $lang)
    {
            $userContext = $this->getUserContext();
            $user = $userContext->getUser();
            $hasEditRight = $page->hasBlockRights($user->getUniqueId(), $blockParams['blockId'], "edit");
            $hasDeleteRight = $page->hasBlockRights($user->getUniqueId(), $blockParams['blockId'], "delete");

            $config = f_loader_Config::getInstance()->getParameters('default');
            $isEditable = $this->isBlockEditable($blockParams);

            $editLink = f_core_Routing::getUrl("editBlock", array("blockId" => $blockParams['blockId'], "docId" => $page->getUniqueId(), "docLang" => strtolower($page->getLang())));
            $rightsLink = f_core_Routing::getUrl("blockRight", array("blockId" => $blockParams['blockId'], "docId" => $page->getUniqueId(), "docLang" => strtolower($page->getLang())));
            $deleteLink = f_core_Routing::getUrl("blockDelete", array("blockId" => $blockParams['blockId'], "docId" => $page->getUniqueId(), "docLang" => strtolower($page->getLang())));
            $infosLink = f_core_Routing::getUrl("blockInfos", array("blockId" => $blockParams['blockId'], "docId" => $page->getUniqueId(), "docLang" => strtolower($page->getLang())));

            $moduleStr = f_locale_Manager::getLocale('website.locales.module', $lang);
            $actionStr = f_locale_Manager::getLocale('website.locales.action', $lang);
            $idStr = f_locale_Manager::getLocale('website.locales.id', $lang);
            $languageStr = f_locale_Manager::getLocale('website.locales.language', $lang);
            $blockDeleteStr = f_locale_Manager::getLocale('website.locales.blockDelete', $lang);
            $blockEditionStr = f_locale_Manager::getLocale('website.locales.blockEdition', $lang);
            $blockRightsStr = f_locale_Manager::getLocale('website.locales.blockRights', $lang);

            $result  = '<div class="blockEditButtons">';

            $result .= '<a href="'.URL_RELATIVE.'/bo/#'.$infosLink.'" class="nyroModal" ><img src="/themes/'.$config['backTheme'].'/backend/medias/icons/1616/info.png" class="toolTip blockInfoImage" title="'.$blockParams['blockLabel'].' - <table><tr><th>'.$moduleStr.'</th><td> : '.$blockParams['module'].'</td></tr><tr><th>'.$actionStr.'</th><td> : '.$blockParams['action'].'</td></tr><tr><th>'.$idStr.'</th><td> : '.$blockParams['blockId'].'</td></tr><tr><th>'.$languageStr.'</th><td> : '.$blockParams['blockLang'].'</td></tr></table>" /></a>';
            
            if($userContext->hasRight("website_TabPageStructure"))
            {
                if($hasDeleteRight)
                {
                    $result .= '<a href="'.URL_RELATIVE.'/bo/#'.$deleteLink.'" class="nyroModal toolTip itemButton itemDeleteButton" title="'.$blockDeleteStr.'"></a>';
                }
            }
            
            if($userContext->hasRight("website_BlockEdit"))
            {
                if($hasEditRight)
                {
                    if($isEditable)
                    {
                        $result .= '<a href="'.URL_RELATIVE.'/bo/#'.$editLink.'" class="nyroModal toolTip itemButton itemEditButton" title="'.$blockEditionStr.'"></a>';
                    }

                    $rightsIcon = 'itemUserButton';
                    if(isset($blockParams['front']))
                    {
                        $rightsIcon = $blockParams['front'] ? "itemLockButton" : "itemUserButton";
                    }

                    $result .= '<a href="'.URL_RELATIVE.'/bo/#'.$rightsLink.'" class="nyroModal toolTip itemButton '.$rightsIcon.'" title="'.$blockRightsStr.'"></a>';
                }
            }

            $result .= '</div>';

            return $result;
    }

    /**
     *
     * @param <type> $options
     * @param <type> $lang
     * @return <type>
     */
    public function searchPagesByBlockParameters($options, $lang = null, $websiteId = null)
    {
        $result = array();
        if(!is_array($options)) return $result;

        if(is_null($lang)) $lang = f_core_Context::getInstance()->getDefaultLang();
        $dbProvider = f_database_Provider::getInstance();

        $query = 'SELECT document_uid FROM `m_website__page` WHERE `content` REGEXP \'';

        foreach($options as $name => $value)
        {
            $query .= $name.'="'.$value.'".*';
        }

        $query .= "' AND document_lang='$lang'";

        if(!is_null($websiteId))
        {
            $query .= " AND websiteId=".$websiteId;
        }

        $res = $dbProvider  ->setQuery($query)
                            ->execute()
                            ->getQueryResults(PDO::FETCH_COLUMN);

        if(count($res) > 0)
        {
            foreach($res as $pageId)
            {
                $result[] = f_document_Provider::getInstance()->getByModelAndUniqueId('website/Page', $pageId, $lang);
            }
        }

        return $result;
    }
}